package com.aspire.aimini.service.impl;

import com.aspire.aimini.entity.Copywriting;
import com.aspire.aimini.repository.CopywritingRepository;
import com.aspire.aimini.service.CopywritingService;
import com.aspire.aimini.service.AiService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 文案服务实现类
 *
 * @author wangguiyou
 * @date 2024-12-19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CopywritingServiceImpl implements CopywritingService {

        private final CopywritingRepository copywritingRepository;
        private final AiService aiService;

        /**
         * 生成文案
         *
         * @param materialId   素材ID
         * @param contentType  内容类型
         * @param style        风格
         * @param requirements 要求
         * @param userId       用户ID
         * @return 生成的文案
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Copywriting generateCopywriting(Long materialId, String contentType, String style,
                        String requirements, Long userId) {
                log.info("生成文案: materialId={}, contentType={}, style={}, userId={}",
                                materialId, contentType, style, userId);

                try {
                        // 调用AI服务生成文案
                        String content = aiService.generateCopywriting(materialId, contentType, style, requirements);

                        Copywriting copywriting = new Copywriting();
                        copywriting.setMaterialId(materialId);
                        copywriting.setContent(content);
                        copywriting.setContentType(contentType);
                        copywriting.setStyle(style);
                        copywriting.setRequirements(requirements);
                        copywriting.setUserId(userId);
                        copywriting.setUsageCount(0);
                        copywriting.setIsFavorite(false);
                        copywriting.setIsDeleted(false);
                        copywriting.setCreatedAt(LocalDateTime.now());
                        copywriting.setUpdatedAt(LocalDateTime.now());

                        copywritingRepository.insert(copywriting);
                        return copywriting;

                } catch (Exception e) {
                        log.error("生成文案失败: materialId={}, error={}", materialId, e.getMessage(), e);
                        throw new RuntimeException("生成文案失败: " + e.getMessage());
                }
        }

        /**
         * 批量生成文案
         *
         * @param materialIds  素材ID列表
         * @param contentType  内容类型
         * @param style        风格
         * @param requirements 要求
         * @param userId       用户ID
         * @return 生成的文案列表
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public List<Copywriting> batchGenerateCopywriting(List<Long> materialIds, String contentType,
                        String style, String requirements, Long userId) {
                log.info("批量生成文案: materialIds={}, contentType={}, style={}, userId={}",
                                materialIds, contentType, style, userId);

                if (materialIds == null || materialIds.isEmpty()) {
                        return Collections.emptyList();
                }

                List<Copywriting> results = new ArrayList<>();
                ;

                for (Long materialId : materialIds) {
                        try {
                                Copywriting copywriting = generateCopywriting(materialId, contentType, style,
                                                requirements, userId);
                                results.add(copywriting);
                        } catch (Exception e) {
                                log.error("批量生成文案失败: materialId={}, error={}", materialId, e.getMessage());
                                // 继续处理其他素材，不中断整个批量操作
                        }
                }

                return results;
        }

        /**
         * 分页查询文案
         *
         * @param page        页码
         * @param size        每页大小
         * @param userId      用户ID
         * @param contentType 内容类型
         * @param style       风格
         * @param keyword     关键词
         * @return 文案分页结果
         */
        @Override
        public Page<Copywriting> getCopywritingsPage(int page, int size, Long userId, String contentType,
                        String style, String keyword) {
                log.info("分页查询文案: page={}, size={}, userId={}, contentType={}, style={}, keyword={}",
                                page, size, userId, contentType, style, keyword);

                Page<Copywriting> pageParam = new Page<>(page, size);
                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();

                wrapper.eq(Copywriting::getIsDeleted, false)
                                .eq(userId != null, Copywriting::getUserId, userId)
                                .eq(StringUtils.hasText(contentType), Copywriting::getContentType, contentType)
                                .eq(StringUtils.hasText(style), Copywriting::getStyle, style)
                                .and(StringUtils.hasText(keyword), w -> w.like(Copywriting::getContent, keyword)
                                                .or().like(Copywriting::getRequirements, keyword))
                                .orderByDesc(Copywriting::getCreatedAt);

                return copywritingRepository.selectPage(pageParam, wrapper);
        }

        /**
         * 根据ID获取文案
         *
         * @param id 文案ID
         * @return 文案信息
         */
        @Override
        public Copywriting getCopywritingById(Long id) {
                log.info("根据ID获取文案: {}", id);

                Copywriting copywriting = copywritingRepository.selectById(id);
                if (copywriting == null || copywriting.getIsDeleted()) {
                        throw new RuntimeException("文案不存在: " + id);
                }
                return copywriting;
        }

        /**
         * 更新文案
         *
         * @param copywriting 文案信息
         * @return 更新后的文案
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Copywriting updateCopywriting(Copywriting copywriting) {
                log.info("更新文案: {}", copywriting.getId());

                getCopywritingById(copywriting.getId()); // 检查文案是否存在

                copywriting.setUpdatedAt(LocalDateTime.now());
                copywritingRepository.updateById(copywriting);

                return getCopywritingById(copywriting.getId());
        }

        /**
         * 删除文案
         *
         * @param id 文案ID
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void deleteCopywriting(Long id) {
                log.info("删除文案: {}", id);

                getCopywritingById(id); // 检查文案是否存在

                LambdaUpdateWrapper<Copywriting> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(Copywriting::getId, id)
                                .set(Copywriting::getIsDeleted, true)
                                .set(Copywriting::getUpdatedAt, LocalDateTime.now());

                copywritingRepository.update(null, wrapper);
        }

        /**
         * 批量删除文案
         *
         * @param ids 文案ID列表
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void deleteCopywritings(List<Long> ids) {
                log.info("批量删除文案: {}", ids);

                if (ids == null || ids.isEmpty()) {
                        return;
                }

                LambdaUpdateWrapper<Copywriting> wrapper = new LambdaUpdateWrapper<>();
                wrapper.in(Copywriting::getId, ids)
                                .set(Copywriting::getIsDeleted, true)
                                .set(Copywriting::getUpdatedAt, LocalDateTime.now());

                copywritingRepository.update(null, wrapper);
        }

        /**
         * 增加文案使用次数
         *
         * @param id 文案ID
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void incrementUsageCount(Long id) {
                log.info("增加文案使用次数: {}", id);

                LambdaUpdateWrapper<Copywriting> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(Copywriting::getId, id)
                                .setSql("usage_count = usage_count + 1")
                                .set(Copywriting::getLastUsedAt, LocalDateTime.now())
                                .set(Copywriting::getUpdatedAt, LocalDateTime.now());

                copywritingRepository.update(null, wrapper);
        }

        /**
         * 获取收藏的文案
         *
         * @param userId 用户ID
         * @param page   页码
         * @param size   每页大小
         * @return 收藏的文案分页结果
         */
        @Override
        public Page<Copywriting> getFavoriteCopywritings(Long userId, int page, int size) {
                log.info("获取收藏的文案: userId={}, page={}, size={}", userId, page, size);

                Page<Copywriting> pageParam = new Page<>(page, size);
                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();

                wrapper.eq(Copywriting::getUserId, userId)
                                .eq(Copywriting::getIsFavorite, true)
                                .eq(Copywriting::getIsDeleted, false)
                                .orderByDesc(Copywriting::getUpdatedAt);

                return copywritingRepository.selectPage(pageParam, wrapper);
        }

        /**
         * 获取最近使用的文案
         *
         * @param userId 用户ID
         * @param limit  数量限制
         * @return 最近使用的文案列表
         */
        @Override
        public List<Copywriting> getRecentCopywritings(Long userId, int limit) {
                log.info("获取最近使用的文案: userId={}, limit={}", userId, limit);

                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Copywriting::getUserId, userId)
                                .eq(Copywriting::getIsDeleted, false)
                                .isNotNull(Copywriting::getLastUsedAt)
                                .orderByDesc(Copywriting::getLastUsedAt)
                                .last("LIMIT " + limit);

                return copywritingRepository.selectList(wrapper);
        }

        /**
         * 获取热门文案
         *
         * @param limit 数量限制
         * @return 热门文案列表
         */
        @Override
        public List<Copywriting> getPopularCopywritings(int limit) {
                log.info("获取热门文案: limit={}", limit);

                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Copywriting::getIsDeleted, false)
                                .gt(Copywriting::getUsageCount, 0)
                                .orderByDesc(Copywriting::getUsageCount)
                                .orderByDesc(Copywriting::getCreatedAt)
                                .last("LIMIT " + limit);

                return copywritingRepository.selectList(wrapper);
        }

        /**
         * 搜索文案
         *
         * @param keyword 关键词
         * @param userId  用户ID
         * @param page    页码
         * @param size    每页大小
         * @return 搜索结果分页
         */
        @Override
        public Page<Copywriting> searchCopywritings(String keyword, Long userId, int page, int size) {
                log.info("搜索文案: keyword={}, userId={}, page={}, size={}", keyword, userId, page, size);

                Page<Copywriting> pageParam = new Page<>(page, size);
                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();

                wrapper.eq(Copywriting::getIsDeleted, false)
                                .eq(userId != null, Copywriting::getUserId, userId)
                                .and(StringUtils.hasText(keyword), w -> w.like(Copywriting::getContent, keyword)
                                                .or().like(Copywriting::getRequirements, keyword)
                                                .or().like(Copywriting::getContentType, keyword)
                                                .or().like(Copywriting::getStyle, keyword))
                                .orderByDesc(Copywriting::getUsageCount)
                                .orderByDesc(Copywriting::getCreatedAt);

                return copywritingRepository.selectPage(pageParam, wrapper);
        }

        /**
         * 按内容类型统计文案数量
         *
         * @param userId 用户ID
         * @return 统计结果
         */
        @Override
        public Map<String, Long> getCountByContentType(Long userId) {
                log.info("按内容类型统计文案数量: userId={}", userId);

                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();
                wrapper.select(Copywriting::getContentType)
                                .eq(Copywriting::getIsDeleted, false)
                                .eq(userId != null, Copywriting::getUserId, userId)
                                .isNotNull(Copywriting::getContentType)
                                .ne(Copywriting::getContentType, "");

                List<Copywriting> copywritings = copywritingRepository.selectList(wrapper);

                return copywritings.stream()
                                .collect(Collectors.groupingBy(
                                                copywriting -> StringUtils.hasText(copywriting.getContentType())
                                                                ? copywriting.getContentType()
                                                                : "未分类",
                                                Collectors.counting()));
        }

        /**
         * 按风格统计文案数量
         *
         * @param userId 用户ID
         * @return 统计结果
         */
        @Override
        public Map<String, Long> getCountByStyle(Long userId) {
                log.info("按风格统计文案数量: userId={}", userId);

                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();
                wrapper.select(Copywriting::getStyle)
                                .eq(Copywriting::getIsDeleted, false)
                                .eq(userId != null, Copywriting::getUserId, userId)
                                .isNotNull(Copywriting::getStyle)
                                .ne(Copywriting::getStyle, "");

                List<Copywriting> copywritings = copywritingRepository.selectList(wrapper);

                return copywritings.stream()
                                .collect(Collectors.groupingBy(
                                                copywriting -> StringUtils.hasText(copywriting.getStyle())
                                                                ? copywriting.getStyle()
                                                                : "未分类",
                                                Collectors.counting()));
        }

        /**
         * 按AI模型统计文案数量
         *
         * @param userId 用户ID
         * @return 统计结果
         */
        @Override
        public Map<String, Long> getCountByAiModel(Long userId) {
                log.info("按AI模型统计文案数量: userId={}", userId);

                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();
                wrapper.select(Copywriting::getAiModel)
                                .eq(Copywriting::getIsDeleted, false)
                                .eq(userId != null, Copywriting::getUserId, userId)
                                .isNotNull(Copywriting::getAiModel)
                                .ne(Copywriting::getAiModel, "");

                List<Copywriting> copywritings = copywritingRepository.selectList(wrapper);

                return copywritings.stream()
                                .collect(Collectors.groupingBy(
                                                copywriting -> StringUtils.hasText(copywriting.getAiModel())
                                                                ? copywriting.getAiModel()
                                                                : "未知模型",
                                                Collectors.counting()));
        }

        /**
         * 获取用户文案统计信息
         *
         * @param userId 用户ID
         * @return 统计信息
         */
        @Override
        public Map<String, Object> getUserCopywritingStatistics(Long userId) {
                log.info("获取用户文案统计信息: userId={}", userId);

                Map<String, Object> statistics = new HashMap<>();

                // 总文案数
                LambdaQueryWrapper<Copywriting> totalWrapper = new LambdaQueryWrapper<>();
                totalWrapper.eq(Copywriting::getUserId, userId)
                                .eq(Copywriting::getIsDeleted, false);
                long totalCount = copywritingRepository.selectCount(totalWrapper);
                statistics.put("totalCount", totalCount);

                // 收藏文案数
                LambdaQueryWrapper<Copywriting> favoriteWrapper = new LambdaQueryWrapper<>();
                favoriteWrapper.eq(Copywriting::getUserId, userId)
                                .eq(Copywriting::getIsFavorite, true)
                                .eq(Copywriting::getIsDeleted, false);
                long favoriteCount = copywritingRepository.selectCount(favoriteWrapper);
                statistics.put("favoriteCount", favoriteCount);

                // 今日生成数
                LocalDateTime todayStart = LocalDate.now().atStartOfDay();
                LocalDateTime todayEnd = todayStart.plusDays(1);
                LambdaQueryWrapper<Copywriting> todayWrapper = new LambdaQueryWrapper<>();
                todayWrapper.eq(Copywriting::getUserId, userId)
                                .eq(Copywriting::getIsDeleted, false)
                                .between(Copywriting::getCreatedAt, todayStart, todayEnd);
                long todayCount = copywritingRepository.selectCount(todayWrapper);
                statistics.put("todayCount", todayCount);

                // 按内容类型统计
                statistics.put("countByContentType", getCountByContentType(userId));

                // 按风格统计
                statistics.put("countByStyle", getCountByStyle(userId));

                return statistics;
        }

        /**
         * 统计每日生成数量
         *
         * @param userId 用户ID
         * @param days   天数
         * @return 每日生成数量统计
         */
        @Override
        public Map<String, Long> getDailyGenerationCount(Long userId, int days) {
                log.info("统计每日生成数量: userId={}, days={}", userId, days);

                LocalDateTime endDate = LocalDate.now().atStartOfDay();
                LocalDateTime startDate = endDate.minusDays(days);

                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Copywriting::getIsDeleted, false)
                                .eq(userId != null, Copywriting::getUserId, userId)
                                .between(Copywriting::getCreatedAt, startDate, endDate);

                List<Copywriting> copywritings = copywritingRepository.selectList(wrapper);

                return copywritings.stream()
                                .collect(Collectors.groupingBy(
                                                copywriting -> copywriting.getCreatedAt().toLocalDate().toString(),
                                                Collectors.counting()));
        }

        /**
         * 清理过期临时文案
         *
         * @param days 天数阈值
         * @return 清理的文案数量
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public int cleanupExpiredTempCopywritings(int days) {
                log.info("清理过期临时文案: days={}", days);

                LocalDateTime threshold = LocalDateTime.now().minusDays(days);

                LambdaQueryWrapper<Copywriting> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(Copywriting::getIsDeleted, false)
                                .eq(Copywriting::getIsTemp, true)
                                .lt(Copywriting::getCreatedAt, threshold);

                List<Copywriting> expiredCopywritings = copywritingRepository.selectList(queryWrapper);

                if (!expiredCopywritings.isEmpty()) {
                        List<Long> ids = expiredCopywritings.stream()
                                        .map(Copywriting::getId)
                                        .collect(Collectors.toList());

                        LambdaUpdateWrapper<Copywriting> updateWrapper = new LambdaUpdateWrapper<>();
                        updateWrapper.in(Copywriting::getId, ids)
                                        .set(Copywriting::getIsDeleted, true)
                                        .set(Copywriting::getUpdatedAt, LocalDateTime.now());

                        copywritingRepository.update(null, updateWrapper);
                }

                return expiredCopywritings.size();
        }

        /**
         * 复制文案
         *
         * @param id     文案ID
         * @param userId 用户ID
         * @return 复制的文案
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Copywriting copyCopywriting(Long id, Long userId) {
                log.info("复制文案: id={}, userId={}", id, userId);

                Copywriting original = getCopywritingById(id);

                Copywriting copy = new Copywriting();
                copy.setMaterialId(original.getMaterialId());
                copy.setContent(original.getContent());
                copy.setContentType(original.getContentType());
                copy.setStyle(original.getStyle());
                copy.setRequirements(original.getRequirements());
                copy.setAiModel(original.getAiModel());
                copy.setUserId(userId);
                copy.setUsageCount(0);
                copy.setIsFavorite(false);
                copy.setIsTemp(false);
                copy.setIsDeleted(false);
                copy.setCreatedAt(LocalDateTime.now());
                copy.setUpdatedAt(LocalDateTime.now());

                copywritingRepository.insert(copy);
                return copy;
        }

        /**
         * 重新生成文案
         *
         * @param id 文案ID
         * @return 重新生成的文案
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Copywriting regenerateCopywriting(Long id) {
                log.info("重新生成文案: id={}", id);

                Copywriting original = getCopywritingById(id);

                return generateCopywriting(
                                original.getMaterialId(),
                                original.getContentType(),
                                original.getStyle(),
                                original.getRequirements(),
                                original.getUserId());
        }

        /**
         * 导出文案
         *
         * @param userId 用户ID
         * @param format 导出格式
         * @return 导出文件路径
         */
        @Override
        public String exportCopywritings(Long userId, String format) {
                log.info("导出文案: userId={}, format={}", userId, format);

                LambdaQueryWrapper<Copywriting> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Copywriting::getUserId, userId)
                                .eq(Copywriting::getIsDeleted, false)
                                .orderByDesc(Copywriting::getCreatedAt);

                List<Copywriting> copywritings = copywritingRepository.selectList(wrapper);

                // TODO: 实现具体的导出逻辑
                // 这里应该根据format参数生成相应格式的文件（如CSV、Excel、JSON等）
                // 并返回文件路径

                return "/exports/copywritings_" + userId + "_" + System.currentTimeMillis() + "."
                                + format.toLowerCase();
        }

        /**
         * 获取可用的内容类型列表
         *
         * @return 内容类型列表
         */
        @Override
        public List<String> getAvailableContentTypes() {
                log.info("获取可用的内容类型列表");

                // 这里可以从配置文件或数据库中获取
                return Arrays.asList(
                                "商品描述",
                                "广告文案",
                                "社交媒体",
                                "新闻稿",
                                "博客文章",
                                "产品介绍",
                                "营销邮件",
                                "视频脚本",
                                "其他");
        }

        /**
         * 获取可用的风格列表
         *
         * @return 风格列表
         */
        @Override
        public List<String> getAvailableStyles() {
                log.info("获取可用的风格列表");

                // 这里可以从配置文件或数据库中获取
                return Arrays.asList(
                                "正式",
                                "轻松",
                                "幽默",
                                "专业",
                                "温馨",
                                "激励",
                                "简洁",
                                "详细",
                                "创意",
                                "传统");
        }
}